﻿$.fn.extend({
    AjaxPage: function (option) {
        var op = {
            "AjaxSource": null,//Ajax处理页面地址,必须提供
            "ContainerID": null,//显示容器ID,必须提供
            "CurrentPage": null,//当前页
            "PageCount": null,  //总页数
            "PageSize": 10,//页面大小
            "PreLoadPage": 20,//预载入页面数量
            "DisplaySize": 10,//可显示页面数量
            "Dom": '{F}首页{/F}{P}上一页{/P}{T}{V}{/T}{N}下一页{/N}{L}尾页{/L}',//分页模板
            "CurrentClass": null,//当前页样式
            "MouseOverClass": null,//鼠标经过样式
            "PostJson": true,
            "DefaultParam": {
                "CurrentPage": "p",
                "PageSize": "s"
            },//默认参数名
            "OtherParam": null,//其它参数
            "Method": "POST",//提交方式
            "contentType": null,
            "dataType": null,   //数据类型
            "TitleDom": null,//标题模板
            "ReData": null,
            "Row": null,
            "EndPage": null //完成跳转页面后调用
        },
        _this = $(this),
        CurrentPage;

        var _preLink = null;
        var _Data = null;
        var _CachePage = { f: 0, e: 0 };

        $.extend(op, option);
        CurrentPage = op.CurrentPage || 1;
        var me = new init();

        function init() {

            nav();

            this.PageCount = function (val) {

                if (val) {
                    op.PageCount = val;
                }

                return op.PageCount;

            }

            this.Repeat = function (val) {

                if (val) {
                    op.PageCount = val;
                }

                nav();
            }
        }

        //生成导航
        function nav() {

            Template(op.Dom);
            EventBind();

        }

        //模版生成器
        function Template(temp) {

            if (temp == null) return "";

            var removeMark = /(^\{[^\/\}]*\})|(\{\/[^\/\}]*\}$)/g;
            var items = temp.match(/(\{F\}[^^]*?\{\/F\})|(\{P\}[^^]*?\{\/P\})|(\{T\}[^^]*?\{\/T\})|(\{N\}[^^]*?\{\/N\})|(\{L\}[^^]*?\{\/L\})|(\{[^\/\}]*\})|([^\{\}]{1,})/g);
            var html = "";

            for (var i in items) {
                //移除标记，并生成HTML
                html += ExecTemp(items[i]);
            }

            _this.empty().append(html);
        }

        function ExecTemp(temp) {
            var removeMark = /(^\{[^\/\}]*\})|(\{\/[^\/\}]*\}$)/g;
            var getMark = /\{[^\/\}]*\}/;
            var mark = temp.match(getMark);

            mark = mark != null ? mark[0] : null;

            if (mark != null) {

                temp = temp.replace(removeMark, "");
                switch (mark) {
                    case "{F}": {
                        return CreateTemp(temp, "f", "1");
                    }
                    case "{P}": {
                        return CreateTemp(temp, "p", "-1");
                    }
                    case "{N}": {
                        return CreateTemp(temp, "n", "1");
                    }
                    case "{L}": {
                        return CreateTemp(temp, "l", op.PageCount);
                    }
                    case "{T}": {
                        var curr = CurrentPage;
                        var pc = op.PageCount;
                        var dp = op.DisplaySize;
                        var mid = parseInt((dp + (dp & 1)) / 2);
                        var fi = 1;
                        var fn = dp;
                        var temps = "";

                        fn = curr == 1 ? fn : curr + mid > pc ? pc : curr + mid;
                        fi = fn == pc ? pc - dp < 0 ? 1 : pc - dp + 1 : fi;
                        fi = curr <= mid ? 1 : fn == pc ? fi : curr - mid + 1;

                        for (; fi <= fn; fi++) {
                            temps += CreateTemp(temp, "t", fi);
                        }

                        return temps;
                    }
                }

            } else {
                return temp;
            }

        }

        function CreateTemp(temp, pro, val) {

            var getMark = /\{V\}/;
            var firstMark = /\<[^\>]*\>/;
            var haveMark = /\<a[^\>]*\>/;

            if (firstMark.test(temp)) {
                var _first = temp.match(firstMark)[0];
                var _mark = temp.match(haveMark);
                temp = temp.replace(_first, _first.replace(">", " pro=\"" + pro + "\">"));

                if (haveMark.test(temp)) {
                    _mark = _mark[0]
                    temp = temp.replace(_mark, _mark.replace(">", " p=\"" + val + "\">"));

                    if (getMark.test(temp)) {
                        temp = temp.replace(getMark, val);
                    }

                } else {

                    if (getMark.test(temp)) {
                        temp = temp.replace(getMark, "<a href=\"#\" p=\"" + val + "\">" + val + "</a>");
                    }

                }

            } else {
                if (getMark.test(temp)) {
                    temp = "<a href=\"#\" pro=\"" + pro + "\" p=\"" + val + "\">" + val + "</a>";
                } else {
                    temp = "<a href=\"#\" pro=\"" + pro + "\" p=\"" + val + "\">" + temp + "</a>"
                }
            }

            return temp;

        }

        function EventBind() {

            var Links = _this.find("[pro]");
            var links = Links.filter("[pro='t']");

            for (var i = 0; i < Links.length; i++) {
                var link = $(Links[i]);

                switch (link.attr("pro")) {
                    case "p": {
                        link.live("click", function () {
                            var c = CurrentPage;
                            c = c - 1;
                            c = c < 1 ? 1 : c;
                            GoPage(links, c);
                            return false;
                        });
                        break;
                    }
                    case "n": {
                        link.live("click", function () {
                            var c = CurrentPage;
                            c = c + 1;
                            c = c > op.PageCount ? op.PageCount : c;
                            GoPage(links, c);
                            return false;
                        });
                        break;
                    }
                    default: {
                        link.live("click", function () {
                            var __this = $(this).find("a:first");
                            __this = __this.length == 0 ? $(this).filter("a:first") : __this;
                            GoPage(links, __this.attr("p"));
                            return false;
                        });
                        break;
                    }
                }

            }

            var defaultLink = links.find("a[p='" + CurrentPage + "']");
            if (defaultLink.length == 0) {
                links.filter("a[p='" + CurrentPage + "']").click();
            } else {
                defaultLink.click();
            }
            Links.removeAttr("pro");

        }

        function GoPage(links, p) {

            if (!p || links.length == 0) return;

            var pc = op.PageCount;
            var dp = op.DisplaySize;
            var mid = parseInt((dp + (dp & 1)) / 2);
            var fi = 1;
            var fn = dp;
            var o;

            p = parseInt(p);
            fn = p == 1 ? fn : p + mid > pc ? pc : p + mid;
            fi = fn == pc ? pc - dp < 0 ? 1 : pc - dp + 1 : fi;
            fi = p <= mid ? 1 : fn == pc ? fi : p - mid + 1;

            if (pc - fi + 1 >= dp) {
                for (var i = 0; i < links.length; i++, fi++) {
                    var link = $(links[i]);

                    if (fi > pc) {
                        link.remove();
                    } else {
                        link.attr("p", fi);
                        $(link.find("a[p]")[0] || link[0]).html(fi);
                    }

                }
            } else {
                for (var i = 0; fi <= fn; fi++, i++) {
                    var link;

                    if (links[i]) {
                        link = $(links[i]);
                    } else {
                        link = $(links[i]).clone();

                        links.after(link);
                    }

                    link.attr("p", fi);
                    $(link.find("a[p]")[0] || link[0]).html(fi);

                }
            }

            o = $(links.find("[p='" + p + "']")[0] || links.filter("[p='" + p + "']")[0]);

            if (op.CurrentClass != null) {

                if (_preLink != null) {
                    _preLink.removeClass(op.CurrentClass);
                }

                _preLink = o;
                o.addClass(op.CurrentClass);

            }

            CurrentPage = p;

            GetData(p);
        }

        //获取数据
        function GetData(p) {

            var d = _Data;
            var c = _CachePage;
            var s = op.PageSize;
            var cp = op.PreLoadPage;
            var dp = op.DisplaySize;
            var pc = op.PageCount;
            var curr = Math.ceil(p / cp);

            curr = curr < 1 ? 1 : curr;

            if (d == null || c.f == 0 || c.f > p || c.e < p) {
                //从数据库获取数据

                var _parm = "";
                var _op = op.OtherParam;

                if (op.PostJson) {
                    _parm += "{"
                             + op.DefaultParam.CurrentPage + ":" + curr + ", "
                             + op.DefaultParam.PageSize + ":" + (cp * s);

                    if (_op) {
                        for (var key in _op) {
                            _parm += ", " + key + ":'" + _op[key].replace("'", "\'") + "'";
                        }
                    }

                    _parm += "}";
                } else {
                    _parm += op.DefaultParam.CurrentPage + "=" + curr + "&"
                             + op.DefaultParam.PageSize + "=" + (cp * s);

                    if (_op) {
                        for (var key in _op) {
                            _parm += "&" + key + "='" + _op[key].replace("'", "\'") + "'";
                        }
                    }
                }

                var ajaxParm = {
                    type: op.Method,
                    url: op.AjaxSource,
                    data: _parm,
                    error: function () { },
                    success: function (_d) {

                        if (typeof op.Row != "function") return;

                        var html = "";
                        var f, e;
                        d = [];

                        if (typeof op.ReData == "function") {
                            _d = op.ReData(_d);
                        }

                        for (var i = 0; i < _d.length; i++) {
                            d[i] = _d[i];
                        }

                        f = p - 1 < 0 ? 0 : p - 1;
                        f = f * s;
                        e = f + s;
                        e = e > d.length ? d.length : e;
                        c.f = (curr - 1) * cp + 1;
                        c.e = curr * cp > pc ? pc : curr * cp;
                        _Data = d;

                        if (f < e) {
                            for (; f < e; f++) {
                                html += op.Row(d[f]);
                            }
                        }

                        html = op.TitleDom ? op.TitleDom + html : html;
                        $("#" + op.ContainerID).html(html);

                        if (typeof op.EndPage == "function") {
                            op.EndPage();
                        }
                    }
                }

                if (op.contentType) ajaxParm.contentType = op.contentType;
                if (op.dataType) ajaxParm.dataType = op.dataType;

                $.ajax(ajaxParm);

            } else {
                var html = "";
                var f, e;

                f = p - 1 < 0 ? 0 : p - 1;
                f = f * s;
                e = f + s;
                e = e > d.length ? d.length : e;

                if (f < e) {
                    for (; f < e; f++) {
                        html += op.Row(d[f]);
                    }
                }

                html = op.TitleDom ? op.TitleDom + html : html;
                $("#" + op.ContainerID).html(html);

                if (typeof op.EndPage == "function") {
                    op.EndPage();
                }
            }
        }

        return me;

    }
});